package com.mlnx.work.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mlnx.common.entity.Response;
import com.mlnx.work.config.ControllerNames;
import com.mlnx.work.entity.*;
import com.mlnx.work.enums.ResponseEnum;
import com.mlnx.work.enums.TaskHandoverStatusEnum;
import com.mlnx.work.enums.ProjectStatusEnum;
import com.mlnx.work.exception.WorkServiceException;
import com.mlnx.work.pojo.dto.DateDTO;
import com.mlnx.work.pojo.form.ArrangeForm;
import com.mlnx.work.pojo.form.OverdueExplainForm;
import com.mlnx.work.pojo.form.OverdueForm;
import com.mlnx.work.pojo.form.TaskForm;
import com.mlnx.work.pojo.vo.TaskListVO;
import com.mlnx.work.service.*;
import com.mlnx.work.utils.DateUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.shan.spring.base.BaseController;
import org.shan.spring.base.annotations.SysLog;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.util.*;

@Api(value = ControllerNames.TaskName + "接口", tags = {ControllerNames.TaskName + "接口"})
@SysLog(title = ControllerNames.TaskName)
@RestController
@RequestMapping("/task")
public class TaskController extends BaseController {
    @Autowired
    private ProjectDirService projectDirService;
    @Autowired
    private ProjectTaskService projectTaskService;
    @Autowired
    private TaskHandoverService taskHandoverService;
    @Autowired
    private TaskMemberService taskMemberService;
    @Autowired
    private ProjectMemberService projectMemberService;
    @Autowired
    private TaskOverdueService taskOverdueService;
    @Autowired
    private TaskArrangeService taskArrangeService;
    @Autowired
    private DepartmentService departmentService;
    @Autowired
    private TaskOverdueExplainService taskOverdueExplainService;

    @ApiOperation("创建项目任务")
    @PostMapping("")
    @Transactional
    public Response createProjectTask(@Valid TaskForm taskForm) {
        //判断是否当前负责人
        if (taskForm.getParentId() > 0) {
            ProjectTask projectTask = projectTaskService.getById(taskForm.getParentId());
            if (projectTask == null || projectTask.getManagerId().intValue() != taskForm.getCreatorId().intValue()) {
                throw new WorkServiceException(ResponseEnum.NONE_PROJECT_AUTHORITY);
            }
        } else {
            ProjectDir projectDir = projectDirService.getById(taskForm.getDirId());
            if (projectDir == null || projectDir.getManagerId().intValue() != taskForm.getCreatorId().intValue()) {
                throw new WorkServiceException(ResponseEnum.NONE_PROJECT_AUTHORITY);
            }
        }

        ProjectTask projectTask = new ProjectTask();
        BeanUtils.copyProperties(taskForm, projectTask);

        projectTask.setCreateTime(System.currentTimeMillis());
        projectTask.setStartTime(0L);
        projectTask.setCompletedTime(0L);
        projectTask.setRisk("");
        projectTask.setWorkHour(0);

        //判断任务是否需要移交
        if (taskForm.getTransferDeptId() > 0) {
            projectTask.setStatus(ProjectStatusEnum.TRANSFERING);
        } else {
            projectTask.setStatus(ProjectStatusEnum.ING);
        }

        projectTaskService.save(projectTask);

        //创建任务移交记录
        if (taskForm.getTransferDeptId() > 0) {
            TaskHandover taskHandover = new TaskHandover();
            taskHandover.setTaskId(projectTask.getId());
            taskHandover.setDeptId(taskForm.getTransferDeptId());
            taskHandover.setStatus(TaskHandoverStatusEnum.ING);

            try {
                taskHandoverService.save(taskHandover);
            } catch (Exception e) {
                logger.error("创建任务移交记录异常");
                e.printStackTrace();
                throw new WorkServiceException(ResponseEnum.MYSQL_OPERATION_EXCEPTION);
            }
        } else {
            //创建任务参与人员关联记录
            try {
                taskMemberService.saveBatch(projectTask.getId(), new Integer[]{taskForm.getManagerId()});
            } catch (Exception e) {
                logger.error("创建任务参与人员关联记录异常");
                e.printStackTrace();
                throw new WorkServiceException(ResponseEnum.MYSQL_OPERATION_EXCEPTION);
            }

            //创建项目参与人员关联记录
            try {
                projectMemberService.saveBatch(projectTask.getDirId(), new Integer[]{projectTask.getManagerId()});
            } catch (Exception e) {
                logger.error("创建项目参与人员关联记录异常");
                e.printStackTrace();
                throw new WorkServiceException(ResponseEnum.MYSQL_OPERATION_EXCEPTION);
            }
        }

        return result(projectTask.getId());
    }

    @ApiOperation("获取部门待移交任务列表")
    @GetMapping("/handover/{deptId}")
    public Response getHandoverTaskList(@PathVariable Integer deptId) {
        return result(taskHandoverService.getByDeptId(deptId));
    }

    @ApiOperation("处理移交任务")
    @PutMapping("/handover/{taskId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "taskId", value = "任务ID", required = true),
            @ApiImplicitParam(name = "managerId", value = "负责人ID", required = true)
    })
    @Transactional
    public Response processHandoverTask(@PathVariable Integer taskId, @RequestParam Integer managerId) {
        ProjectTask projectTask = new ProjectTask();
        projectTask.setId(taskId);
        projectTask.setManagerId(managerId);
        projectTask.setStatus(ProjectStatusEnum.ING);

        projectTaskService.updateById(projectTask);

        TaskHandover taskHandover = new TaskHandover();
        taskHandover.setTaskId(taskId);
        taskHandover.setStatus(TaskHandoverStatusEnum.DONE);

        try {
            taskHandoverService.update(taskHandover, new QueryWrapper<TaskHandover>().eq("task_id", taskId));
        } catch (Exception e) {
            logger.error("更新任务移交状态异常");
            throw new WorkServiceException(ResponseEnum.MYSQL_OPERATION_EXCEPTION);
        }

        try {
            taskMemberService.saveBatch(taskId, new Integer[]{managerId});
        } catch (Exception e) {
            logger.error("创建任务参与人员关联记录异常");
            throw new WorkServiceException(ResponseEnum.MYSQL_OPERATION_EXCEPTION);
        }

        try {
            projectMemberService.saveBatch(projectTask.getDirId(), new Integer[]{projectTask.getManagerId()});
        } catch (Exception e) {
            logger.error("创建项目参与人员关联记录异常");
            throw new WorkServiceException(ResponseEnum.MYSQL_OPERATION_EXCEPTION);
        }

        return result();
    }

    @ApiOperation("添加任务参与人员")
    @PostMapping("/member/{taskId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "taskId", value = "任务ID", required = true),
            @ApiImplicitParam(name = "memberIds", value = "参与人ID集合", required = true)
    })
    @Transactional
    public Response addTaskMember(@PathVariable Integer taskId, @RequestParam Integer[] memberIds) {
        taskMemberService.saveBatch(taskId, memberIds);

        ProjectTask projectTask = projectTaskService.getById(taskId);
        try {
            projectMemberService.saveBatch(projectTask.getDirId(), memberIds);
        } catch (Exception e) {
            logger.error("创建项目参与人员关联记录异常");
            throw new WorkServiceException(ResponseEnum.MYSQL_OPERATION_EXCEPTION);
        }

        return result();
    }

    @ApiOperation("获取个人任务列表")
    @GetMapping("/list/{memberId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "memberId", value = "参与人ID", required = true)
    })
    public Response getTaskList(@PathVariable Integer memberId) {
        List<TaskListVO> taskListVOS = projectTaskService.getByMember(memberId);

        //处理返回形式
        Map<String, List<TaskListVO>> resultMap = new HashMap<>();
        resultMap.put("today", new ArrayList<>());
        resultMap.put("overdue", new ArrayList<>());
        resultMap.put("others", new ArrayList<>());
        Long curr = System.currentTimeMillis();
        for (TaskListVO taskListVO : taskListVOS) {
            switch (DateUtil.dateCompare(taskListVO.getOriginEndTime(), curr)) {
                case -1:
                    resultMap.get("overdue").add(taskListVO);
                    break;
                case 0:
                    resultMap.get("today").add(taskListVO);
                    break;
                case 1:
                    resultMap.get("others").add(taskListVO);
                    break;
            }
        }
        return result(resultMap);
    }

    @ApiOperation("获取日历任务列表")
    @GetMapping("/calendar/{memberId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "memberId", value = "参与人ID", required = true),
            @ApiImplicitParam(name = "startTime", value = "起始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true)
    })
    public Response getTaskList(@PathVariable Integer memberId, @RequestParam Long startTime, @RequestParam Long endTime) {
        DateDTO dateDTO = new DateDTO(startTime, endTime);
        List<TaskListVO> taskListVOS = projectTaskService.getByMember(memberId, dateDTO);

//        //处理返回形式
//        Map<Integer, List<TaskListVO>> resultMap = new HashMap<>();
//        Calendar calendar = Calendar.getInstance();
//        for (TaskListVO taskListVO : taskListVOS) {
//            calendar.setTimeInMillis(taskListVO.getOriginEndTime());
//            int day = calendar.get(Calendar.DAY_OF_MONTH);
//            if (resultMap.containsKey(day)) {
//                resultMap.get(day).add(taskListVO);
//            } else {
//                List<TaskListVO> newList = new ArrayList<>();
//                newList.add(taskListVO);
//                resultMap.put(day, newList);
//            }
//        }

        return result(taskListVOS);
    }

    @ApiOperation("设置任务风险项")
    @PutMapping("/risk/{taskId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "taskId", value = "任务ID", required = true),
            @ApiImplicitParam(name = "risk", value = "风险项", required = true),
            @ApiImplicitParam(name = "managerId", value = "负责人ID", required = true)
    })
    public Response setTaskRisk(@PathVariable Integer taskId, @RequestParam String risk, @RequestParam Integer managerId) {
        ProjectTask projectTask = projectTaskService.getById(taskId);
        if (projectTask.getManagerId().intValue() != managerId.intValue()) {
            throw new WorkServiceException(ResponseEnum.NONE_PROJECT_AUTHORITY);
        }

        projectTask = new ProjectTask();
        projectTask.setId(taskId);
        projectTask.setRisk(risk);

        projectTaskService.updateById(projectTask);

        return result();
    }

    @ApiOperation("提交任务完成")
    @PutMapping("/{taskId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "taskId", value = "任务ID", required = true),
            @ApiImplicitParam(name = "managerId", value = "负责人ID", required = true),
            @ApiImplicitParam(name = "workHour", value = "工时", required = true)
    })
    public Response completeTask(@PathVariable Integer taskId, @RequestParam Integer managerId, @RequestParam Integer workHour) {
        ProjectTask projectTask = projectTaskService.getById(taskId);
        if (projectTask.getManagerId().intValue() != managerId.intValue()) {
            throw new WorkServiceException(ResponseEnum.NONE_PROJECT_AUTHORITY);
        }

        //检查子任务是否全部完成
        List<ProjectTask> childTasks = projectTaskService.getByParentId(taskId);
        boolean allCompleted = true;
        for (ProjectTask childTask : childTasks) {
            if (!childTask.getStatus().equals(ProjectStatusEnum.DONE)) {
                allCompleted = false;
                break;
            }
        }

        if (!allCompleted) {
            throw new WorkServiceException(ResponseEnum.CHILD_NOT_COMPLETED);
        }

        projectTask.setWorkHour(workHour);
        projectTask.setStatus(ProjectStatusEnum.DONE_VERIFY);
        projectTask.setCompletedTime(System.currentTimeMillis());
        projectTaskService.updateById(projectTask);

        return result();
    }

    @ApiOperation("获取部门下待确认完成任务列表")
    @GetMapping("/completed/verify/{deptId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "deptId", value = "部门ID", required = true)
    })
    public Response getVerifyTaskList(@PathVariable Integer deptId) {
        return result(projectTaskService.getVerifyTaskListByDept(deptId));
    }

    @ApiOperation("部门负责人确认任务完成")
    @PutMapping("/completed/{taskId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "taskId", value = "任务ID", required = true),
            @ApiImplicitParam(name = "deptManagerId", value = "部门负责人ID", required = true)
    })
    public Response verifyTask(@PathVariable Integer taskId, @RequestParam Integer deptManagerId) {
        //校验权限
        Department department = departmentService.getDeptByTask(taskId);
        if (department == null || department.getManagerId().intValue() != deptManagerId.intValue()) {
            throw new WorkServiceException(ResponseEnum.NONE_PROJECT_AUTHORITY);
        }

        ProjectTask projectTask = new ProjectTask();
        projectTask.setId(taskId);
        projectTask.setStatus(ProjectStatusEnum.DONE);

        projectTaskService.updateById(projectTask);

        return result();
    }

    @ApiOperation("添加项目逾期")
    @PostMapping("/overdue")
    @Transactional
    public Response addTaskOverdue(@Valid OverdueForm overdueForm) {
        ProjectTask projectTask = projectTaskService.getById(overdueForm.getId());
        if (DateUtil.dateCompare(overdueForm.getOverdueTime(), projectTask.getOriginEndTime()) < 1) {
            throw new WorkServiceException(ResponseEnum.INVALID_OVERDUE);
        }

        TaskOverdue taskOverdue = new TaskOverdue();
        BeanUtils.copyProperties(overdueForm, taskOverdue);
        taskOverdue.setTaskId(overdueForm.getId());
        taskOverdue.setCommitTime(System.currentTimeMillis());
        taskOverdueService.save(taskOverdue);
        List<OverdueExplainForm> overdueDescription = overdueForm.getOverdueDescription();
        for (OverdueExplainForm overdueExplain : overdueDescription){
            if (DateUtil.dateCompare(taskOverdue.getOverdueTime(), overdueExplain.getOverdueTime()) < 1) {
                throw new WorkServiceException(ResponseEnum.OVERDUE_TIME_OVER);//逾期计划说明最大时间不能超过项目逾期时间
            }
            TaskOverdueExplain taskOverdueExplain = new TaskOverdueExplain();
            BeanUtils.copyProperties(overdueExplain, taskOverdueExplain);
            taskOverdueExplain.setParentId(taskOverdue.getId());
            taskOverdueExplain.setCommitTime(System.currentTimeMillis());
            taskOverdueExplainService.save(taskOverdueExplain);
        }
        return result();
    }

//    @ApiOperation("添加项目逾期说明")
//    @PostMapping("/overdueExplain")
//    @Transactional
//    public Response addTaskOverdueExplain(@Valid OverdueExplainForm overdueExplainForm) {
//        TaskOverdue taskOverdue = taskOverdueService.getById(overdueExplainForm.getId());
//        if (DateUtil.dateCompare(taskOverdue.getOverdueTime(), overdueExplainForm.getOverdueTime()) < 1) {
//            throw new WorkServiceException(ResponseEnum.OVERDUE_TIME_OVER);//逾期计划说明最大时间不能超过项目逾期时间
//        }
//        TaskOverdueExplain taskOverdueExplain = new TaskOverdueExplain();
//        BeanUtils.copyProperties(overdueExplainForm, taskOverdueExplain);
//        taskOverdueExplain.setParentId(overdueExplainForm.getId());
//        taskOverdueExplain.setCommitTime(System.currentTimeMillis());
//        taskOverdueExplainService.save(taskOverdueExplain);
//        return result();
//    }

    @ApiOperation("添加任务周计划")
    @PostMapping("/arrange")
    public Response addTaskArrange(@Valid ArrangeForm arrangeForm) {
        TaskArrange taskArrange = new TaskArrange();
        BeanUtils.copyProperties(arrangeForm, taskArrange);
        taskArrange.setTaskId(arrangeForm.getId());
        taskArrange.setCommitTime(System.currentTimeMillis());

        taskArrangeService.save(taskArrange);

        return result();
    }

    @ApiOperation("获取任务详情")
    @GetMapping("/detail/{taskId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "taskId", value = "任务ID", required = true)
    })
    public Response getParentTaskDetail(@PathVariable Integer taskId) {
        return result(projectTaskService.getParentTaskById(taskId));
    }

    @ApiOperation("设置项目实际开始时间")
    @PutMapping("/startTime/{taskId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "taskId", value = "任务ID", required = true),
            @ApiImplicitParam(name = "startTime", value = "项目实际开始时间", required = true),
            @ApiImplicitParam(name = "managerId", value = "负责人ID", required = true)
    })
    public Response setTaskStartTime(@PathVariable Integer taskId, @RequestParam Long startTime, @RequestParam Integer managerId) {
        ProjectTask projectTask = projectTaskService.getById(taskId);
        if (projectTask.getStartTime() > 0)
            throw new WorkServiceException(ResponseEnum.START_TIME_SET_ALREADY);

        if (projectTask.getManagerId().intValue() != managerId.intValue())
            throw new WorkServiceException(ResponseEnum.NONE_PROJECT_AUTHORITY);

        projectTask = new ProjectTask();
        projectTask.setId(taskId);
        projectTask.setStartTime(startTime);

        projectTaskService.updateById(projectTask);
        return result();
    }
}
